﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Infraestruturex.Automata.SPA;
using Compilex.BaseLibrary;

namespace Metex
{
    public class SPAReferenceSolver
    {
        public Dictionary<string, SPA> Submachines { get; private set; }

        public SPAReferenceSolver(Dictionary<string, SPA> submachines)
        {
            this.Submachines = submachines;
        }

        public SPA SolveReferences(SPA spa)
        {
            SPAState[] states = spa.GetStates();
            foreach(SPAState state in states)
            {
                // as transições do estado, menos transições stub para submáquina
                List<SimpleTransitionRuleWithSemanticAction> newTransitions =
                    new List<SimpleTransitionRuleWithSemanticAction>();

                foreach(SimpleTransitionRuleWithSemanticAction transition in state.Transitions.ToArray())
                {
                    if (transition.Input.StartsWith("_$") && transition.Input.EndsWith("$_"))
                    {
                        string submachineToCall = transition.Input.Substring(2, transition.Input.Length - 4);
                        if (Submachines.ContainsKey(submachineToCall))
                        {
                            if (state.IsSubmachineCallState == false)
                            {
                                state.IsSubmachineCallState = true;
                                state.SubmachineCallReturnState = transition.Destination;
                                state.SubmachineToCall = Submachines[submachineToCall];
                            }
                            else
                            {
                                throw new ArgumentException("O estado " + state.Name + " tem mais de uma chamada de submáquina");
                            }
                        }
                        else
                        {
                            throw new ArgumentException("Referência não resolvida: " + submachineToCall);
                        }
                    }
                    else
                    {
                        newTransitions.Add(transition);
                    }
                }

                state.Transitions = new SimpleList<SimpleTransitionRuleWithSemanticAction>();
                newTransitions.ForEach(t => state.Transitions.Add(t));

            }
            return spa;
        }
    }
}
